package cn.coder.jdbc2.config.builder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import cn.coder.jdbc2.config.Configuration;
import cn.coder.jdbc2.config.MappedStatement;
import cn.coder.jdbc2.config.SqlSource;
import cn.coder.jdbc2.util.ClassUtil;

public class XmlMapperBuilder {

	private InputStream inputStream;
	private Configuration configuration;
	private String namespace;

	public XmlMapperBuilder(InputStream inputStream, Configuration configuration) {
		// TODO Auto-generated constructor stub
		this.inputStream = inputStream;
		this.configuration = configuration;
	}

	public void parse() {
		// TODO Auto-generated method stub
		Document document = null;
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			// 禁用外部实体，防止XXE
			factory.setExpandEntityReferences(false);
			document = factory.newDocumentBuilder().parse(this.inputStream);
		} catch (SAXException | IOException | ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (document == null)
			return;
		// Document document = DocumentReader.createDocument(inputStream);
		// Element element = document.getRootElement();
		Element element = document.getDocumentElement();
		this.namespace = element.getAttribute("namespace");

		if (this.namespace == null || this.namespace.equals("")) {
			throw new RuntimeException("Mapper的namespace值不能为空");
		}

		// 解析所有select标签
		parseSelectStatements(element.getElementsByTagName("select"));
		// 解析所有insert标签
		parseInsertStatements(element.getElementsByTagName("insert"));
	}

	private void parseSelectStatements(NodeList nodeList) {
		for (int i = 0; i < nodeList.getLength(); i++) {
			if (nodeList.item(i) instanceof Element) {
				parseSelectStatement((Element) nodeList.item(i));
			}
		}
	}

	private void parseSelectStatement(Element element) {
		// TODO Auto-generated method stub
		String id = this.namespace + "." + element.getAttribute("id");
		Class<?> parameterTypeClass = ClassUtil.getClazz(element.getAttribute("parameterType"));
		Class<?> resultTypeClass = ClassUtil.getClazz(element.getAttribute("resultType"));
		String statementType = element.getAttribute("statementType");
		SqlSource sqlSource = new SqlSource(element.getTextContent().trim());

		MappedStatementBuilder msBuilder = new MappedStatementBuilder();
		MappedStatement mappedStatement = msBuilder.id(id).parameterTypeClass(parameterTypeClass)
				.resultTypeClass(resultTypeClass).statementType(statementType).sqlSource(sqlSource).builder();

		configuration.addMappedStatement(id, mappedStatement);

	}

	private void parseInsertStatements(NodeList nodeList) {
		// TODO Auto-generated method stub
	}

}
